﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;

namespace NewKataminoSolver
{
    class Board
    {
        // local data needed
        public int W, H; // size of the board in width, height
        public int[,] D;  // penta cover data 1..12, or 0 if empty
        public int fw, fh; // index of firstFree
        public Bitmap picture;
        public static Color[] palette = { Color.White,
                                      Color.Blue, Color.Red, Color.Green, Color.Brown, Color.Purple, Color.Orange,
                                      Color.LightBlue, Color.Pink, Color.LightGreen, Color.Yellow, Color.Violet, Color.Lime,
                                      Color.WhiteSmoke};

        // Methods needed:

        // constructor
        public Board()
        {
            W = 0;
            H = 0;
            D = new int[W, H];
            picture = new Bitmap(W, H);
        }
        public Board(Board b)
        {
            this.W = b.W;
            this.H = b.H;
            this.D = (int[,])b.D.Clone();
            this.picture = (Bitmap)b.picture.Clone();
        }
        public Board(int w, int h)
        {
            W = w;
            H = h;
            D = new int[W, H];
            picture = new Bitmap(20 * W, 20 * H);
            Graphics graph = Graphics.FromImage(picture);
            graph.Clear(Color.White);
            graph.Dispose();
        }

        public bool firstFree()
        {
            fh = 0;
            fw = 0;
            for (int ih = 0; ih < H; ih++)
                for (int iw = 0; iw < W; iw++)
                    if (D[iw, ih] == 0)
                    {
                        fw = iw;
                        fh = ih;
                        Brush b = new SolidBrush(palette[13]);
                        Graphics graph = Graphics.FromImage(this.picture);
                        graph.FillRectangle(b, 1 + 20 * fw, 1 + 20 * fh, 20, 20);
                        graph.Dispose();
                        return true;
                    }
            return false; // if no free field was found
        }
        public bool firstFreeYX()
        {
            fh = 0;
            fw = 0;
            for (int iw = 0; iw < W; iw++)
                for (int ih = 0; ih < H; ih++)
                    if (D[iw, ih] == 0)
                    {
                        fw = iw;
                        fh = ih;
                        return true;
                    }
            return false; // if no free field was found
        }
        public bool firstFreeX()
        {
            fh = 0;
            fw = 0;
            for (int ii = 0; ii < W + H; ii++)
                for (int ih = 0, iw = ii-ih; ih < H && iw >= 0 && iw < W; ih++)
                    if (D[iw, ih] == 0)
                    {
                        fw = iw;
                        fh = ih;
                        return true;
                    }
            return false; // if no free field was found
        }
        public bool pentaFree(Penta p)
        {
            bool result = true;
            if ((p.box.Left + fw < 0) || (p.box.Right + fw >= W)
                || (p.box.Height + fh >= H))
                return false; // box + fh >= 0 by definition
            
            for (int ip = 0; ip < p.x.Length && ip < p.y.Length; ip++)
                result = result && (D[p.x[ip] + fw, p.y[ip] + fh] == 0);

            return result;
        }

        public Board Add(Penta p, int number)
        {
            Board result = new Board(this);
            Graphics graph = Graphics.FromImage(result.picture);

            for (int ip = 0; ip < p.x.Length && ip < p.y.Length; ip++)
            {
                result.D[p.x[ip] + fw, p.y[ip] + fh] = number;
                Brush b = new SolidBrush(palette[number]);
                graph.FillRectangle(b, 1+20*(p.x[ip] + fw), 1+20*(p.y[ip] + fh), 20, 20);
            }
            result.firstFree(); // update the first free field
            graph.Flush();
            graph.Dispose();
            
            return result;
        }
    }
}
